package com.fengyunhe.mobile;

import com.fengyunhe.manager.AppException;
import com.fengyunhe.wechat.mp.WeChatApp;
import com.fengyunhe.wechat.mp.api.WeChat;
import com.fengyunhe.wechat.mp.api.bean.UserAccessToken;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.view.RedirectView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 功能：微信WEB辅助类，需要微信用户参与的页面可以继承此类解决授权问题
 * 作者： yangyan
 * 时间： 2015/6/7 .
 */
public class WeChatUserSupportController {
    Logger log = LoggerFactory.getLogger(WeChatUserSupportController.class);
    /**
     * 微信授权用户的TOKEN存储在session中的key
     */
    public static final String SESSION_KEY_USER_TOKEN = "wx_token";

    @Autowired
    WeChat weChat;
    @Autowired
    WeChatApp weChatApp;

    /**
     * 判断当前访问微信用户是否授权
     *
     * @return
     */
    protected boolean isAuthed() {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        Object attribute = request.getSession() == null ? null : request.getSession().getAttribute(SESSION_KEY_USER_TOKEN);
        return attribute != null;
    }

    /**
     * 获取当前微信授权微信用户的token
     *
     * @return
     */
    protected UserAccessToken getToken() {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        Object attribute = request.getSession() == null ? null : request.getSession().getAttribute(SESSION_KEY_USER_TOKEN);
        return (UserAccessToken) attribute;
    }

    /**
     * 获取当前微信用户的OpenId
     *
     * @return
     */
    protected String getOpenId() {
        UserAccessToken token = this.getToken();
        if (token != null) {
            return token.getOpenid();
        }
        return null;
    }

    /**
     * 授权只获取用户的openId时使用此方法跳转
     *
     * @param redirectUrl
     * @param state
     * @return
     */
    protected ModelAndView baseAuth(String redirectUrl, String state) {
        String authorizationBaseUrl = weChat.getUserApi().getAuthorizationBaseUrl(redirectUrl, state);
        return new ModelAndView(new RedirectView(authorizationBaseUrl, false));
    }

    /**
     * 授权需要获取用户的OpenId和基本信息时使用此方法调转
     *
     * @param redirectUrl
     * @param state
     * @return
     */
    protected ModelAndView userAuth(String redirectUrl, String state) {
        String authorizationBaseUrl = weChat.getUserApi().getAuthorizationUserInfoUrl(redirectUrl, state);
        return new ModelAndView(new RedirectView(authorizationBaseUrl, false));
    }

    /**
     * 此方法的功能是使用code换取微信用户的token，然后将token保存在用户的session中。应该在自己的HTTP请求处理方法中构造callback，然后调用此方法
     *
     * @param state
     * @param code
     * @param callback
     * @return
     */
    protected ModelAndView callbackAuth(String code, String state, OAuthCallback callback) {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getResponse();
        UserAccessToken accessToken = null;
        if (callback == null) {
            try {
                response.getWriter().print("Error,callback is required");
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
        if (StringUtils.isNotBlank(code)) {
            try {
                accessToken = weChat.getUserApi()
                        .getAccessToken(code);
            } catch (Exception e) {
                log.error("微信用户授权发生异常", e);
                return callback.failure(request, response, state, new AppException("微信用户授权时发生异常", e));
            }
        }
        if (accessToken != null) {
            request.getSession(true).setAttribute(SESSION_KEY_USER_TOKEN, accessToken);
            return callback.success(request, response, state);
        } else {
            return callback.failure(request, response, state, null);
        }
    }

    /**
     * 授权结果回调处理抽象类,不同场景下的授权回调处理应该继承此类根据不同的场景做处理
     */
    public static abstract class OAuthCallback {

        /**
         * 授权成功的时候进入此方法执行
         *
         * @param state 授权返回时带有的参数
         * @return 跳转到什么地方
         */
        public abstract ModelAndView success(HttpServletRequest request, HttpServletResponse response, String state);


        /**
         * 授权失败的时候进入此方法执行
         *
         * @param state     授权返回时带有的参数
         * @param exception 授权抛出的异常
         * @return 跳转到什么地方
         */
        public abstract ModelAndView failure(HttpServletRequest request, HttpServletResponse response, String state, AppException exception);
    }
}
